<template>
  <div class="kanban-container">
    <PageLoading 
      v-if="loading && !requirements.length"
      title="正在加载看板数据"
      subtitle="请稍候..."
    />
    <el-empty v-else-if="!loading && !requirements.length" description="暂无需求数据" />
    <el-scrollbar v-else class="kanban-scroll">
      <div class="kanban-board">
        <div
          v-for="column in columns"
          :key="column.key"
          class="kanban-column"
          :class="{ disabled: column.disabled }"
          :data-status="column.key"
        >
        <header class="column-header">
          <div class="column-title">
            <span class="dot" :style="{ background: column.color }" />
            <strong>{{ column.title }}</strong>
          </div>
          <div class="column-header-right">
            <span class="column-count">{{ column.items.length }}</span>
            <el-tooltip content="新建需求" placement="top">
              <el-button
                type="primary"
                circle
                plain
                size="small"
                class="create-button"
                @click.stop="handleCreateRequirement(column.key)"
              >
                <el-icon><Plus /></el-icon>
              </el-button>
            </el-tooltip>
          </div>
        </header>

        <el-scrollbar class="column-scroll">
          <Draggable
            :list="column.items"
            item-key="id"
            class="column-scroll-list"
            :component-data="{ attrs: { 'data-status': column.key } }"
            group="requirement-status"
            :animation="180"
            :disabled="loading || column.disabled"
            @start="handleDragStart"
            @end="(event: any) => handleDragEnd(event)"
          >
            <template #item="{ element }">
              <el-card
                :data-requirement-id="element.id"
                :data-id="element.id"
                shadow="never"
                class="kanban-card"
                @click="$emit('open-detail', element.id)"
              >
                <div class="card-header">
                  <div class="card-id-wrapper">
                    <span class="card-id">#{{ element.id.slice(-8) }}</span>
                    <el-tag 
                      v-if="element.requirement_type" 
                      size="small" 
                      type="info"
                      class="type-tag"
                    >
                      {{ getTypeText(element.requirement_type) }}
                    </el-tag>
                  </div>
                  <el-tag size="small" :type="priorityTagType(element.priority)" class="priority-tag">
                    {{ getPriorityLabel(element.priority) }}
                  </el-tag>
                </div>
                <div class="card-title" :title="element.title">{{ element.title }}</div>
                <div class="card-meta">
                  <div class="meta-item">
                    <UserDisplay
                      :user-id="element.assignee_id"
                      :user-name="element.assignee_name"
                      :show-avatar="true"
                      size="small"
                    />
                  </div>
                  <div class="meta-item" v-if="element.project_name">
                    <el-icon class="meta-icon"><Folder /></el-icon>
                    <span class="meta-text">{{ element.project_name }}</span>
                  </div>
                </div>
                <div class="card-footer">
                  <span class="time">
                    <el-icon class="time-icon"><Clock /></el-icon>
                    {{ formatDate(element.updated_at) }}
                  </span>
                  <div class="card-actions">
                    <el-button 
                      type="primary" 
                      text 
                      size="small" 
                      class="action-button"
                      @click.stop="$emit('open-edit', element.id)"
                    >
                      <el-icon><Edit /></el-icon>
                    </el-button>
                    <el-button 
                      type="danger" 
                      text 
                      size="small" 
                      class="action-button delete-button"
                      @click.stop="handleDeleteClick(element)"
                    >
                      <el-icon><Delete /></el-icon>
                    </el-button>
                  </div>
                </div>
              </el-card>
            </template>
          </Draggable>
        </el-scrollbar>
        </div>
      </div>
    </el-scrollbar>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Folder, Clock, Edit, Delete } from '@element-plus/icons-vue'
import dayjs from 'dayjs'
import Draggable from 'vuedraggable'
import type { RequirementResponse, RequirementType } from '@/api/requirements'
import { deleteRequirement } from '@/api/requirements'
import { useRequirementOptions } from '@/composables/useRequirementOptions'
import { ResponseParser } from '@/utils/responseParser'
import UserDisplay from '@/components/ui/UserDisplay.vue'
import PageLoading from '@/components/ui/PageLoading.vue'

const props = defineProps<{
  requirements: RequirementResponse[]
  statusOptions: Array<{ value: string; label: string; color?: string; disabled?: boolean; is_enabled?: boolean }>
  priorityOptions: Array<{ value: string; label: string }>
  loading: boolean
}>()

const emit = defineEmits<{
  (event: 'open-detail', id: string): void
  (event: 'open-edit', id: string): void
  (event: 'update-status', payload: { id: string; status: string }): void
  (event: 'create-requirement', status: string): void
  (event: 'deleted', id: string): void
}>()

const deletingIds = ref<Set<string>>(new Set())

const recycleColumn = {
  key: 'unclassified',
  title: '未分类',
  color: '#c9ccd8',
  disabled: false,
  is_enabled: true
}

const getPriorityLabel = (value?: string | null) => {
  if (!value) return '未设置'
  return props.priorityOptions.find(option => option.value === value)?.label ?? value
}

const { getTypeName } = useRequirementOptions()

const getTypeText = (type?: RequirementType | string | null) => {
  if (!type) return ''
  return getTypeName(String(type))
}

const priorityTagType = (priority?: string | null) => {
  const code = priority?.toLowerCase()
  switch (code) {
    case 'critical':
    case 'urgent':
      return 'danger'
    case 'high':
      return 'warning'
    case 'medium':
      return 'success'
    default:
      return 'info'
  }
}

const formatDate = (value?: string) => {
  if (!value) return '—'
  return dayjs(value).format('MM-DD HH:mm')
}

const columns = computed(() => {
  const map = new Map<string, RequirementResponse[]>()
  props.statusOptions.forEach(option => map.set(option.value, []))

  const fallback: RequirementResponse[] = []

  props.requirements.forEach(item => {
    if (item.status && map.has(item.status)) {
      map.get(item.status)?.push(item)
    } else {
      fallback.push(item)
    }
  })

  const result = props.statusOptions.map(option => ({
    key: option.value,
    title: option.label,
    color: option.color || '#528bff',
    items: map.get(option.value) || [],
    disabled: option.disabled || false,
    is_enabled: option.is_enabled !== false // 默认为 true，除非明确设置为 false
  }))

  if (fallback.length) {
    result.push({
      ...recycleColumn,
      items: fallback
    })
  }

  return result
})

const handleCreateRequirement = (status: string) => {
  emit('create-requirement', status)
}

// 处理删除点击
async function handleDeleteClick(requirement: RequirementResponse) {
  if (!requirement.id) {
    return
  }

  // 如果正在删除，直接返回
  if (deletingIds.value.has(requirement.id)) {
    return
  }

  try {
    await ElMessageBox.confirm(
      `确定要删除需求"${requirement.title}"吗？此操作不可恢复。`,
      '删除确认',
      {
        confirmButtonText: '确定删除',
        cancelButtonText: '取消',
        type: 'warning',
        confirmButtonClass: 'el-button--danger',
        beforeClose: async (action, instance, done) => {
          if (action === 'confirm') {
            instance.confirmButtonLoading = true
            try {
              await performDelete(requirement.id!)
              done()
            } catch (error) {
              instance.confirmButtonLoading = false
            }
          } else {
            done()
          }
        }
      }
    )
  } catch (error) {
    // 用户取消删除
    if (error !== 'cancel') {
      console.error('删除确认对话框错误:', error)
    }
  }
}

// 执行删除操作
async function performDelete(requirementId: string) {
  if (deletingIds.value.has(requirementId)) {
    return
  }

  deletingIds.value.add(requirementId)
  try {
    const response = await deleteRequirement(requirementId)
    const parsed = ResponseParser.parseResponse(response)
    
    if (!parsed.success) {
      throw new Error(parsed.message || '删除失败')
    }

    ElMessage.success('删除成功')
    emit('deleted', requirementId)
  } catch (error) {
    const message = ResponseParser.extractMessage(error) || '删除失败'
    ElMessage.error(message)
    throw error
  } finally {
    deletingIds.value.delete(requirementId)
  }
}

const handleDragStart = () => {
  // 添加拖拽状态类，用于全局样式控制
  document.body.classList.add('dragging')
}

const handleDragEnd = async (event: any) => {
  // 移除拖拽状态类
  document.body.classList.remove('dragging')
  
  const { item, from, to, oldIndex, newIndex } = event || {}
  
  if (!item || !from || !to) {
    return
  }
  
  // 从 DOM 元素获取目标状态（查找最近的 .kanban-column）
  const targetColumn = to.closest?.('.kanban-column') || to.parentElement?.closest?.('.kanban-column')
  const finalTargetStatus = targetColumn?.getAttribute('data-status') || 
    targetColumn?.dataset?.status ||
    to?.getAttribute('data-status') ||
    to?.dataset?.status
  
  // 获取源状态
  const sourceColumn = from.closest?.('.kanban-column') || from.parentElement?.closest?.('.kanban-column')
  const sourceStatus = sourceColumn?.getAttribute('data-status') || 
    sourceColumn?.dataset?.status ||
    from?.getAttribute('data-status') ||
    from?.dataset?.status
  
  // 检查状态是否真的改变了
  if (finalTargetStatus === sourceStatus) {
    // 同一列内移动，不需要更新状态
    return
  }
  
  if (!finalTargetStatus) {
    console.warn('无法获取目标状态', { targetColumn, to, event })
    // 恢复原始位置
    if (oldIndex !== undefined && from) {
      const children = from.children
      if (children[oldIndex]) {
        from.insertBefore(item, children[oldIndex])
      } else if (oldIndex === 0) {
        from.insertBefore(item, children[0])
      } else {
        from.appendChild(item)
      }
    }
    return
  }
  
  // 验证目标状态是否在状态选项中（确保状态是可见的）
  const targetStatusOption = props.statusOptions.find(opt => opt.value === finalTargetStatus)
  if (!targetStatusOption) {
    console.warn('目标状态不在可用状态列表中，无法拖入', { 
      finalTargetStatus, 
      availableStatuses: props.statusOptions.map(opt => opt.value),
      statusOptions: props.statusOptions
    })
    ElMessage.warning(`无法将需求拖入"${finalTargetStatus}"状态，该状态可能已被禁用或不存在`)
    // 恢复原始位置
    if (oldIndex !== undefined && from) {
      const children = from.children
      if (children[oldIndex]) {
        from.insertBefore(item, children[oldIndex])
      } else if (oldIndex === 0) {
        from.insertBefore(item, children[0])
      } else {
        from.appendChild(item)
      }
    }
    return
  }

  // 检查目标状态是否启用（如果禁用，不允许拖动）
  if (targetStatusOption.disabled || targetStatusOption.is_enabled === false) {
    console.warn('目标状态已被禁用，无法拖入', { 
      finalTargetStatus,
      targetStatusOption
    })
    ElMessage.warning(`无法将需求拖入"${targetStatusOption.label}"状态，该状态已被禁用`)
    // 恢复原始位置
    if (oldIndex !== undefined && from) {
      const children = from.children
      if (children[oldIndex]) {
        from.insertBefore(item, children[oldIndex])
      } else if (oldIndex === 0) {
        from.insertBefore(item, children[0])
      } else {
        from.appendChild(item)
      }
    }
    return
  }
  
  // 获取需求ID - 优先使用 data-requirement-id，其次使用 data-id
  let requirementId = item.getAttribute?.('data-requirement-id') ||
    item.dataset?.requirementId ||
    item.getAttribute?.('data-id') ||
    item.dataset?.id
  
  // 方法2: 从卡片的子元素中查找
  if (!requirementId) {
    const cardElement = item.querySelector?.('.kanban-card')
    if (cardElement) {
      requirementId = cardElement.getAttribute('data-requirement-id') ||
        cardElement.getAttribute('data-id') ||
        cardElement.dataset?.requirementId ||
        cardElement.dataset?.id
    }
  }
  
  // 方法3: 尝试从 event.itemContext 或 item.__draggable_context 获取
  if (!requirementId && event?.itemContext) {
    requirementId = event.itemContext.element?.id
  }
  
  if (!requirementId && item.__draggable_context) {
    requirementId = item.__draggable_context.element?.id
  }
  
  // 方法4: 作为最后手段，从目标列的 items 数组中根据 newIndex 获取
  // 注意：此时列表可能已被 vuedraggable 更新，newIndex 处可能是新移动的元素
  if (!requirementId && typeof newIndex === 'number' && newIndex >= 0) {
    const targetColumnData = columns.value.find(col => col.key === finalTargetStatus)
    if (targetColumnData && targetColumnData.items[newIndex]) {
      requirementId = targetColumnData.items[newIndex].id
    }
  }
  
  if (!requirementId) {
    console.warn('拖拽事件缺少需求ID:', { item, from, to, oldIndex, newIndex, event })
    // 恢复原始位置
    if (oldIndex !== undefined && from) {
      const children = from.children
      if (children[oldIndex]) {
        from.insertBefore(item, children[oldIndex])
      } else if (oldIndex === 0) {
        from.insertBefore(item, children[0])
      } else {
        from.appendChild(item)
      }
    }
    ElMessage.error('无法获取需求信息，请重试')
    return
  }

  // 传递对象参数，匹配 emit 类型定义
  // 父组件会处理状态更新，如果失败会重新加载数据
  emit('update-status', { id: requirementId, status: finalTargetStatus })
}
</script>

<style scoped>
.kanban-container {
  min-height: 0;
  min-width: 0;
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.kanban-scroll {
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  height: 100%;
}

.kanban-scroll :deep(.el-scrollbar) {
  height: 100%;
}

.kanban-scroll :deep(.el-scrollbar__wrap) {
  overflow-y: hidden;
  overflow-x: auto;
  height: 100%;
}

.kanban-board {
  display: flex;
  gap: 16px;
  padding-bottom: 4px;
  min-height: 100%;
  width: max-content;
}

.kanban-column {
  display: flex;
  flex-direction: column;
  flex: 0 0 280px;
  height: calc(100vh - 280px);
  min-height: 400px;
  max-height: calc(100vh - 200px);
  border-radius: 16px;
  background: linear-gradient(180deg, #ffffff 0%, #f4f7ff 100%);
  box-shadow: inset 0 0 0 1px rgba(91, 118, 184, 0.12);
  overflow: hidden;
  position: relative;
  transition: opacity 0.3s ease;
}

.kanban-column.disabled {
  opacity: 0.6;
  background: linear-gradient(180deg, #f5f5f5 0%, #e8e8e8 100%);
  cursor: not-allowed;
}

.kanban-column.disabled .column-scroll-list {
  pointer-events: none;
}

.column-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 16px;
  border-bottom: 1px solid rgba(102, 126, 185, 0.12);
}

.column-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  color: #264074;
}

.column-title .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.column-header-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.column-count {
  font-size: 12px;
  color: #7582a4;
}

.create-button {
  flex-shrink: 0;
}

.column-scroll {
  flex: 1;
  padding: 12px 12px 6px;
  min-height: 0;
  height: 100%;
  overflow: hidden;
}

.column-scroll :deep(.el-scrollbar) {
  height: 100%;
}

.column-scroll :deep(.el-scrollbar__wrap) {
  height: 100%;
  overflow-x: hidden;
  overflow-y: auto !important;
}

.column-scroll :deep(.el-scrollbar__view) {
  min-height: auto;
}

.column-scroll :deep(.el-scrollbar__bar) {
  right: 2px;
}

.column-scroll :deep(.el-scrollbar__bar.is-vertical) {
  width: 6px;
}

.column-scroll :deep(.el-scrollbar__thumb) {
  background-color: rgba(144, 147, 153, 0.3);
  border-radius: 3px;
}

.column-scroll :deep(.el-scrollbar__thumb:hover) {
  background-color: rgba(144, 147, 153, 0.5);
}

.column-scroll-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-height: auto;
}

.kanban-card {
  margin-bottom: 12px;
  border-radius: 12px;
  cursor: pointer;
  border: 1px solid #e4e7ed;
  background: #ffffff;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  position: relative;
  overflow: hidden;
}

.kanban-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 3px;
  height: 100%;
  background: linear-gradient(180deg, #409eff 0%, #66b1ff 100%);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.kanban-card:hover {
  transform: translateY(-4px);
  border-color: #409eff;
  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
}

.kanban-card:hover::before {
  opacity: 1;
}

.kanban-card:active {
  transform: translateY(-2px);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
}

.kanban-card :deep(.el-card__body) {
  padding: 14px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 10px;
  gap: 8px;
}

.card-id-wrapper {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  min-width: 0;
}

.card-id {
  font-size: 11px;
  color: #909399;
  font-weight: 500;
  font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
  letter-spacing: 0.5px;
}

.type-tag {
  font-size: 10px;
  padding: 0 6px;
  height: 18px;
  line-height: 18px;
}

.priority-tag {
  flex-shrink: 0;
  font-size: 11px;
  padding: 0 8px;
  height: 20px;
  line-height: 20px;
  font-weight: 500;
}

.card-title {
  font-weight: 600;
  font-size: 14px;
  color: #303133;
  margin-bottom: 12px;
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: break-word;
  min-height: 42px;
  transition: color 0.2s ease;
}

.kanban-card:hover .card-title {
  color: #409eff;
}

.card-meta {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
  padding-top: 8px;
  border-top: 1px solid #f0f2f5;
}

.meta-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: #606266;
}

.meta-icon {
  font-size: 14px;
  color: #909399;
  flex-shrink: 0;
}

.meta-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.meta-text.text-muted {
  color: #c0c4cc;
}

.card-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 10px;
  border-top: 1px solid #f0f2f5;
}

.time {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: #909399;
}

.time-icon {
  font-size: 12px;
}

.card-actions {
  display: flex;
  align-items: center;
  gap: 4px;
}

.action-button {
  padding: 4px 8px;
  opacity: 0.7;
  transition: all 0.2s ease;
}

.kanban-card:hover .action-button {
  opacity: 1;
}

.action-button:hover {
  opacity: 1;
  background-color: #ecf5ff;
}

.action-button:not(.delete-button):hover {
  color: #409eff;
}

.delete-button:hover {
  color: #f56c6c;
  background-color: #fef0f0;
}
</style>

